﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WorkFlowCore.IRepositories;
using WorkFlowCore.WorkTasks;

namespace WorkFlowCore.Framework.Repositories
{
    public class WorkTaskRepository : BasicRepository<WorkTaskInfo, Guid>, IWorkTaskRepository
    {
        private readonly IWorkStepRepository workStepRepository;

        public WorkTaskRepository(IUnitOfWork unitOfWork,IWorkStepRepository workStepRepository) : base(unitOfWork)
        {
            this.workStepRepository = workStepRepository;
        }

        public async Task<PageResult<WorkTask>> GetAllTasksOfUserAsync(string userId, int pageIndex = 1, int pageSize = -1)
        {
            var workTaskIds = (await workStepRepository.GetListAsync(ws => ws.HandleUser_Id == userId)).Select(ws => ws.WorkTaskId);

            var result = new PageResult<WorkTask>
            {
                Total = await GetCountAsync(wt => workTaskIds.Contains(wt.Id))
            };
            if (pageSize < 1)
                result.Items = (await GetListAsync(wt => workTaskIds.Contains(wt.Id))).Select(w => w.ToWorkTask()).ToList();
            else result.Items = (await GetPagedListAsync(wt => workTaskIds.Contains(wt.Id), (pageIndex - 1) * pageSize, pageSize, "CreationTime desc")).Select(w => w.ToWorkTask()).ToList();
            return await Task.FromResult(result);
        }

        public async Task<PageResult<WorkTask>> GetHandledWorkTasksOfUserAsync(string userId, int pageIndex = 1, int pageSize = -1)
        {
            var workTaskIds = (await workStepRepository.GetListAsync(ws => ws.HandleUser_Id == userId && ws.IsHandled)).Select(ws => ws.WorkTaskId);

            var workTasks = (await GetListAsync(wt => workTaskIds.Contains(wt.Id) && !wt.IsSimulation)).OrderByDescending(ws => ws.CreationTime);

            var result = new PageResult<WorkTask>
            {
                Total = await GetCountAsync(wt => workTaskIds.Contains(wt.Id) && !wt.IsSimulation)
            };

            if (pageSize < 1)
                result.Items = (await Task.FromResult(workTasks.Select(w => w.ToWorkTask()))).ToList();
            else result.Items = (await Task.FromResult(workTasks.Select(w => w.ToWorkTask()).Skip((pageIndex - 1) * pageSize).Take(pageSize))).ToList();

            return await Task.FromResult(result);
        }

        public async Task<PageResult<WorkTask>> GetTasksOfStartUserAsync(string userId, int pageIndex = 1, int pageSize = -1)
        {
            var result = new PageResult<WorkTask>
            {
                Total = (await GetCountAsync(wt => wt.ModifiedUserId == userId))
            };
            if (pageSize < 1)
                result.Items = (await GetListAsync(wt => wt.ModifiedUserId == userId)).Select(ws=>ws.ToWorkTask()).ToList();
            else result.Items = (await GetPagedListAsync(wt => wt.ModifiedUserId == userId, (pageIndex - 1) * pageSize, pageSize, "")).Select(w => w.ToWorkTask()).ToList();
            return await Task.FromResult(result);
        }

        public async Task<PageResult<WorkTask>> GetUnHandledWorkTasksOfUserAsync(string userId, int pageIndex = 1, int pageSize = -1)
        {
            var workTaskIds = (await workStepRepository.GetListAsync(ws => ws.HandleUser_Id == userId && !ws.IsHandled)).Select(ws => ws.WorkTaskId);

            var workTasks = (await GetListAsync(wt => workTaskIds.Contains(wt.Id)&&!wt.IsSimulation)).OrderByDescending(ws => ws.CreationTime);

            var result = new PageResult<WorkTask>
            {
                Total = await GetCountAsync(wt => workTaskIds.Contains(wt.Id) && !wt.IsSimulation)
            };

            if (pageSize < 1)
                result.Items =( await Task.FromResult(workTasks.Select(w => w.ToWorkTask()))).ToList();
            else result.Items =(await Task.FromResult(workTasks.Select(w => w.ToWorkTask()).Skip((pageIndex - 1) * pageSize).Take(pageSize))).ToList();

            return await Task.FromResult(result);
        }

        public async Task<PageResult<WorkTask>> GetWorkflowedTasksOfUserAsync(string userId, int pageIndex = 1, int pageSize = -1)
        {
            var workTaskIds = (await workStepRepository.GetListAsync(ws => ws.HandleUser_Id == userId && ws.IsHandled)).Select(ws => ws.WorkTaskId);
            var result = new PageResult<WorkTask>
            {
                Total = await GetCountAsync(wt => workTaskIds.Contains(wt.Id))
            };


            if (pageSize < 1)
                result.Items = (await GetListAsync(wt => workTaskIds.Contains(wt.Id))).OrderByDescending(ws => ws.CreationTime).Select(ws => ws.ToWorkTask()).ToList();
            else result.Items = (await GetListAsync(wt => workTaskIds.Contains(wt.Id))).OrderByDescending(ws => ws.CreationTime).Select(ws => ws.ToWorkTask()).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
            return await Task.FromResult(result);
        }

        public async Task<PageResult<WorkTask>> GetWorkTasksOfCreatorAsync(string userId, int pageIndex = 1, int pageSize = -1)
        {
            var workTaskIds = (await workStepRepository.GetListAsync(ws => ws.CreatedUserId == userId && ws.IsHandled)).Select(ws => ws.WorkTaskId);

            var workTasks = (await GetListAsync(wt => workTaskIds.Contains(wt.Id) && !wt.IsSimulation)).OrderByDescending(ws => ws.CreationTime);

            var result = new PageResult<WorkTask>
            {
                Total = await GetCountAsync(wt => workTaskIds.Contains(wt.Id) && !wt.IsSimulation)
            };

            if (pageSize < 1)
                result.Items = (await Task.FromResult(workTasks.Select(w => w.ToWorkTask()))).ToList();
            else result.Items = (await Task.FromResult(workTasks.Select(w => w.ToWorkTask()).Skip((pageIndex - 1) * pageSize).Take(pageSize))).ToList();

            return await Task.FromResult(result);
        }

        public async Task<PageResult<WorkTask>> GetAllWorkTasksAsync(int pageIndex = 1, int pageSize = -1)
        {
            var workTaskIds = (await workStepRepository.GetListAsync(null)).Select(ws => ws.WorkTaskId);

            var workTasks = (await GetListAsync(wt => workTaskIds.Contains(wt.Id) && !wt.IsSimulation)).OrderByDescending(ws => ws.CreationTime);

            var result = new PageResult<WorkTask>
            {
                Total = await GetCountAsync(wt => workTaskIds.Contains(wt.Id) && !wt.IsSimulation)
            };

            if (pageSize < 1)
                result.Items = (await Task.FromResult(workTasks.Select(w => w.ToWorkTask()))).ToList();
            else result.Items = (await Task.FromResult(workTasks.Select(w => w.ToWorkTask()).Skip((pageIndex - 1) * pageSize).Take(pageSize))).ToList();

            return await Task.FromResult(result);
        }
    }
}
